using NativeWebSocket;
using System;
using UnityEngine;

namespace SinceTimes.NetWork
{
    public class ConnectionNativeWebSocket : Connection
    {
        public  WebSocket WS;

        public override float Latency => 0;// WS!=null&& WS.IsOpen? WS.Latency/1000f :0;

        byte[] _BUFF = new byte[4096];
        public ConnectionNativeWebSocket(MonoBehaviour owner) : base(owner)
        {

        }


        public override bool Connected => WS != null && WS.State ==   WebSocketState.Open;


        public override string State => WS != null ? WS.State.ToString() : "NULL";



        protected override void _DoConnect() => _ConnectAsync();//Owner.StartCoroutine(_Conntect_Runer()); 


        async void _ConnectAsync()
        {
            base._DoConnect();

            string url = Url;



            if (Port > 0)
                url = $"{url}:{Port}";

            WS=new WebSocket(url);

            WS.OnOpen+=()=>
            {
                Debug.Log($"[ConnectionNativeWebSocket.WS.OnOpen]:State={WS.State}.................");
                _OnOpen();
            };
            WS.OnError += (e) =>
            {

                Debug.Log($"[ConnectionNativeWebSocket.WS.OnError ]:e={e}.................");

                _DoError(e);
            };
            WS.OnClose += (e) =>
            {
                Debug.Log($"[ConnectionNativeWebSocket.WS.OnClose]:e={e}.................");
                Error = $"{e}";
                _DoClose();
            };
            //WS.OnMessage += (bytes) =>
            //{
            //    _OnBinary(WS, bytes);
            //};

            await   WS.Connect();

            if (Net.SHOWLOG) Debug.Log($"[ConnectionNativeWebSocket.WS.Open({url})].................");         
        }


        async void _OnOpen()
        {
            //if (!ws.State=) return;
            if (Net.SHOWLOG)  Debug.Log($"[ConnectionNativeWebSocket._OnOpen]:State={WS.State}.................");


            //如果有身份验证...
            if (_Buff_Authenticate != null && _Buff_Authenticate.Length > 0)
            {

                if (Net.SHOWLOG) Debug.Log($"[ConnectionNativeWebSocket._OnOpen]:SendAsync:_Buff_Author:{Net.BYTES_STRING(_Buff_Authenticate)}");
                
                //发送身份验证
                await WS.Send(_Buff_Authenticate);

                if (UserAuthCheckable)
                {
                    // 需要等待身份验证...
                    WS.OnMessage += _OnBinary_Authenticate;

                }
                else
                {

                    //启动正常 接受回调...
                    WS.OnMessage += _OnBinary;
                    OnConnectSuccess();
                }


            }
            else//不需要身份验证...直接正常启动链接成功....
            {
                //启动正常 接受回调...
                WS.OnMessage += _OnBinary;
                OnConnectSuccess();
            }


        }

        protected override async void _DoClose(bool callback = false)
        {
            if (Net.SHOWLOG) Debug.Log($"[ConnectionNativeWebSocket._DoClose]:State={WS.State}.................");
            if (WS != null && (WS.State== WebSocketState.Open || WS.State== WebSocketState.Connecting) )
                await    WS.Close();

            base._DoClose(callback);
        }
        //接受身份验证逻辑包..
        void _OnBinary_Authenticate( byte[] data)
        {
            if (Net.SHOWLOG) Debug.Log($"[ConnectionNativeWebSocket._OnBinary_Authenticate({Net.BYTES_STRING(data)})].................");
            //如果包 合法
            if (data.Length > 0)
            {
                ushort len = Net.BYTE_USHORT(data, 0); //消息报长度
                ushort type = Net.BYTE_USHORT(data, 2);//消息类型

                if ( type == 20002)
                {
                    Error = "";

                    //启动正常 接受回调...
                    WS.OnMessage -= _OnBinary_Authenticate;
                    WS.OnMessage += _OnBinary;


                    OnConnectSuccess();

                    return;
                }
            }

            _DoError("Authenticate Error");
        }



        //接受正常逻辑包..
        void _OnBinary( byte[] data)
        {

            if (Net.SHOWLOG)Debug.Log($"[ConnectionNativeWebSocket._OnBinary]:data[{data.Length}].................");

            if (data == null || data.Length < 1)
            {
                _DoClose(true);
                return;
            }

            RuntimeState.Receiving = true;
            _OnReceive(data, 0, (uint)data.Length);
        }


        protected override  int _DoSend(byte[] data)
        {
            try
            {
                 WS.Send(data);
                _OnSend(data);
                return data.Length;
            }
            catch(Exception e)
            {
                Error = e.Message;
                _DoClose(true);return 0;
            }

           
        }

        protected override void RuntimeCheck()
        {
            base.RuntimeCheck();

            RuntimeState.State = (WS != null ? WS.State.ToString() : "null");

        }
        public override void Loop()
        {
            base.Loop();

#if !UNITY_WEBGL || UNITY_EDITOR
            WS.DispatchMessageQueue();
#endif
        }
    }

}
